import dayjs from 'dayjs'
import { omitBy, isNil, isNumber, isEmpty } from 'lodash-es'

// 日期格式化
// NOTE: 目前仅用在模板代码生成部分
export function parseTime(time: Date | string, pattern: string) {
  return dayjs(time).format(pattern)
}

// 添加日期范围
export function addDateRange(params, dateRange, propName?) {
  const search = params
  search.params =
    typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params)
      ? search.params
      : {}
  dateRange = Array.isArray(dateRange) ? dateRange : []
  if (typeof propName === 'undefined') {
    search.params['beginTime'] = dateRange[0]
    search.params['endTime'] = dateRange[1]
  } else {
    search.params['begin' + propName] = dateRange[0]
    search.params['end' + propName] = dateRange[1]
  }
  return search
}

// 回显数据字典
export function selectDictLabel(datas, value) {
  if (value === undefined) {
    return ''
  }
  const actions = []
  Object.keys(datas).some((key) => {
    if (datas[key].value == '' + value) {
      actions.push(datas[key].label)
      return true
    }
  })
  if (actions.length === 0) {
    actions.push(value)
  }
  return actions.join('')
}

// 回显数据字典（字符串数组）
export function selectDictLabels(datas, value, separator) {
  if (value === undefined || value.length === 0) {
    return ''
  }
  if (Array.isArray(value)) {
    value = value.join(',')
  }
  const actions = []
  const currentSeparator = undefined === separator ? ',' : separator
  const temp = value.split(currentSeparator)
  Object.keys(value.split(currentSeparator)).some((val) => {
    let match = false
    Object.keys(datas).some((key) => {
      if (datas[key].value == '' + temp[val]) {
        actions.push(datas[key].label + currentSeparator)
        match = true
      }
    })
    if (!match) {
      actions.push(temp[val] + currentSeparator)
    }
  })
  return actions.join('').substring(0, actions.join('').length - 1)
}

// 数据合并
export function mergeRecursive(source, target) {
  for (const p in target) {
    try {
      if (target[p].constructor == Object) {
        source[p] = mergeRecursive(source[p], target[p])
      } else {
        source[p] = target[p]
      }
    } catch (e) {
      source[p] = target[p]
    }
  }
  return source
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export function handleTree(data, id, parentId, children) {
  const config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children',
  }

  const childrenListMap = {}
  const nodeIds = {}
  const tree = []

  for (const d of data) {
    const parentId = d[config.parentId]
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = []
    }
    nodeIds[d[config.id]] = d
    childrenListMap[parentId].push(d)
  }

  for (const d of data) {
    const parentId = d[config.parentId]
    if (nodeIds[parentId] == null) {
      tree.push(d)
    }
  }

  for (const t of tree) {
    adaptToChildrenList(t)
  }

  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]]
    }
    if (o[config.childrenList]) {
      for (const c of o[config.childrenList]) {
        adaptToChildrenList(c)
      }
    }
  }
  return tree
}

// 验证是否为blob格式
export async function blobValidate(data) {
  try {
    const text = await data.text()
    JSON.parse(text)
    return false
  } catch (error) {
    return true
  }
}

/**
 * 去除对象中值为空的属性
 * @param obj 要进行处理的对象
 * @returns 处理后的对象
 */
export function omitEmptyValue(obj: Object) {
  return omitBy(obj, isEmptyValue)
}

export function isEmptyValue(v: number | null | undefined | string) {
  if (isNil(v)) return true
  if (isNumber(v)) return false
  return isEmpty(v)
}

/**
 * 将当前单位的大小转变为能转变的最大单位大小
 * @param size 当前单位的大小
 * @param level 当前单位在enum中的值
 * @param step 跨度 默认是1024
 * @param sizeEnum 大小单位数组，默认是文件单位
 * @param showLevel 返回结果是否带单位，默认是
 * @returns 转变后的大小
 */
export function convertToMaxSize(
  originSize,
  level = 0,
  step = 1024,
  sizeEnum = ['B', 'KB', 'MB', 'GB']
) {
  let size = originSize
  let unit = sizeEnum[level]
  if (!originSize) {
    size = 0
  }
  let _level = level // 0-b 1-kb 2-mb 3-gb
  while (size / step >= 1 && _level <= sizeEnum.length - 2) {
    _level += 1
    size = originSize / step ** _level
  }
  unit = sizeEnum[_level]

  function format() {
    return size.toFixed(2).toString() + unit
  }
  return {
    size,
    unit,
    format,
  }
}

/**
 * 去除数字小数点的多余0
 * @param num
 * @returns
 */
export function trimNumber(num) {
  const str = num.toString()
  const stripped = str.replace(/(\.\d*[1-9])0+$/, '$1')
  return parseFloat(stripped)
}

export function formatDate(value: string | Date | null, pattern: string = 'YYYY-MM-DD HH:mm:ss') {
  if (isNil(value) || isEmpty(value)) return ''
  return dayjs(value).format(pattern)
}
